package cn.dyw.engine.core.exec;

import cn.dyw.engine.core.context.ReportStandardContext;
import cn.dyw.engine.core.exception.EngineRenderException;
import cn.dyw.engine.core.limit.DefaultLimitRender;
import cn.dyw.engine.core.limit.ILimitRender;
import cn.dyw.engine.core.order.DefaultSortRender;
import cn.dyw.engine.core.order.ISortRender;
import cn.dyw.engine.core.page.DefaultPageRender;
import cn.dyw.engine.core.page.IPageRender;
import cn.dyw.engine.core.template.ITemplateEngine;
import com.alibaba.druid.DbType;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * 默认实现执行引擎
 *
 * @author dyw770
 * @since 2021-08-03
 */
@Data
@Slf4j
public class DefaultReportExecEngine extends AbstractReportExecEngine {

    /**
     * 默认排序
     */
    private static final ISortRender DEFAULT_SORT = new DefaultSortRender();

    /**
     * 默认limit
     */
    private static final ILimitRender DEFAULT_LIMIT = new DefaultLimitRender();

    /**
     * 默认的page渲染
     */
    private static final IPageRender DEFAULT_PAGE = new DefaultPageRender(DEFAULT_LIMIT);

    static {

    }

    /**
     * 排序渲染
     */
    private Map<DbType, ISortRender> sortRenderMap = new HashMap<>();

    /**
     * limit渲染
     */
    private Map<DbType, ILimitRender> limitRenderMap = new HashMap<>();

    /**
     * 分页渲染
     */
    private Map<DbType, IPageRender> pageRenderMap = new HashMap<>();


    private ITemplateEngine templateEngine;

    public DefaultReportExecEngine(ITemplateEngine templateEngine) {
        this.templateEngine = templateEngine;
    }

    public void addSortRender(DbType dbType, ISortRender sortRender) {
        sortRenderMap.put(dbType, sortRender);
    }

    public void addLimitRender(DbType dbType, ILimitRender limitRender) {
        limitRenderMap.put(dbType, limitRender);
    }

    public void addPageRender(DbType dbType, IPageRender pageRender) {
        pageRenderMap.put(dbType, pageRender);
    }

    @Override
    public void render(ReportStandardContext context) throws EngineRenderException {
        context.setExecSql(templateEngine.process(context));
    }

    @Override
    public void sort(ReportStandardContext context) {
        ISortRender sortRender = sortRenderMap.getOrDefault(context.getDbType(), DEFAULT_SORT);
        log.info("使用 [{}] 渲染排序", sortRender.getClass());
        context.setExecSql(sortRender.sortRender(context.getExecSql(), context));
    }

    @Override
    public void limit(ReportStandardContext context) {
        ILimitRender render = limitRenderMap.getOrDefault(context.getDbType(), DEFAULT_LIMIT);
        log.info("使用 [{}] 渲染limit", render.getClass());
        context.setExecSql(render.limitRender(context.getExecSql(), context));
    }

    @Override
    public void page(ReportStandardContext context) throws EngineRenderException {
        IPageRender pageRender = pageRenderMap.getOrDefault(context.getDbType(), DEFAULT_PAGE);
        log.info("使用 [{}] 渲染分页语句", pageRender.getClass());
        context.setExecSql(pageRender.pageRender(context.getExecSql(), context));
    }

}
